#!/bin/bash

# 高考志愿推荐系统启动脚本 - JVM优化版本
# 专门解决StackOverflowError问题，不截断任何数据

echo "=== 高考志愿推荐系统启动 - JVM优化版本 ==="
echo "启动时间: $(date)"
echo ""

# 检查Java版本
JAVA_VERSION=$(java -version 2>&1 | head -n1 | cut -d'"' -f2)
echo "Java版本: $JAVA_VERSION"

# 检查可用内存
TOTAL_MEM=$(free -m | awk 'NR==2{printf "%.0f", $2/1024}')
echo "系统总内存: ${TOTAL_MEM}GB"

# 根据系统内存调整JVM参数
if [ "$TOTAL_MEM" -ge 16 ]; then
    # 16GB以上内存的配置
    HEAP_MAX="12g"
    HEAP_MIN="6g"
    NEW_SIZE="4g"
    STACK_SIZE="16m"
    echo "使用大内存配置: 堆内存12GB, 栈大小16MB"
elif [ "$TOTAL_MEM" -ge 8 ]; then
    # 8-16GB内存的配置
    HEAP_MAX="6g"
    HEAP_MIN="3g"
    NEW_SIZE="2g"
    STACK_SIZE="8m"
    echo "使用中等内存配置: 堆内存6GB, 栈大小8MB"
else
    # 8GB以下内存的配置
    HEAP_MAX="4g"
    HEAP_MIN="2g"
    NEW_SIZE="1g"
    STACK_SIZE="4m"
    echo "使用小内存配置: 堆内存4GB, 栈大小4MB"
fi

# 创建日志目录
mkdir -p logs

# 设置应用JAR文件路径
APP_JAR="yudao-server.jar"
if [ ! -f "$APP_JAR" ]; then
    echo "错误: 找不到应用JAR文件 $APP_JAR"
    exit 1
fi

# JVM优化参数
JVM_OPTS=""

# 基础内存参数
JVM_OPTS="$JVM_OPTS -server"
JVM_OPTS="$JVM_OPTS -Xmx$HEAP_MAX"
JVM_OPTS="$JVM_OPTS -Xms$HEAP_MIN"
JVM_OPTS="$JVM_OPTS -Xmn$NEW_SIZE"
JVM_OPTS="$JVM_OPTS -Xss$STACK_SIZE"

# G1垃圾收集器配置
JVM_OPTS="$JVM_OPTS -XX:+UseG1GC"
JVM_OPTS="$JVM_OPTS -XX:MaxGCPauseMillis=200"
JVM_OPTS="$JVM_OPTS -XX:G1HeapRegionSize=16m"
JVM_OPTS="$JVM_OPTS -XX:G1NewSizePercent=30"
JVM_OPTS="$JVM_OPTS -XX:G1MaxNewSizePercent=40"
JVM_OPTS="$JVM_OPTS -XX:ConcGCThreads=4"
JVM_OPTS="$JVM_OPTS -XX:ParallelGCThreads=8"

# 内存优化
JVM_OPTS="$JVM_OPTS -XX:+UseCompressedOops"
JVM_OPTS="$JVM_OPTS -XX:+UseCompressedClassPointers"
JVM_OPTS="$JVM_OPTS -XX:+UseStringDeduplication"
JVM_OPTS="$JVM_OPTS -XX:G1MixedGCLiveThresholdPercent=85"

# GC日志配置
JVM_OPTS="$JVM_OPTS -XX:+PrintGC"
JVM_OPTS="$JVM_OPTS -XX:+PrintGCDetails"
JVM_OPTS="$JVM_OPTS -XX:+PrintGCTimeStamps"
JVM_OPTS="$JVM_OPTS -XX:+PrintGCApplicationStoppedTime"
JVM_OPTS="$JVM_OPTS -Xloggc:logs/gc-$(date +%Y%m%d-%H%M%S).log"

# 错误处理配置
JVM_OPTS="$JVM_OPTS -XX:+HeapDumpOnOutOfMemoryError"
JVM_OPTS="$JVM_OPTS -XX:HeapDumpPath=logs/heapdump-$(date +%Y%m%d-%H%M%S).hprof"
JVM_OPTS="$JVM_OPTS -XX:+PrintCrashReports"
JVM_OPTS="$JVM_OPTS -XX:ErrorFile=logs/hs_err_pid%p-$(date +%Y%m%d-%H%M%S).log"

# 性能监控配置
JVM_OPTS="$JVM_OPTS -XX:+PrintCommandLineFlags"
JVM_OPTS="$JVM_OPTS -XX:+UnlockExperimentalVMOptions"
JVM_OPTS="$JVM_OPTS -XX:+UseCGroupMemoryLimitForHeap"

# 应用特定配置
APP_OPTS=""
APP_OPTS="$APP_OPTS --spring.profiles.active=prod"
APP_OPTS="$APP_OPTS --server.port=8080"
APP_OPTS="$APP_OPTS --logging.file.path=logs"
APP_OPTS="$APP_OPTS --logging.level.cn.iocoder.yudao.module.system.service.gugu=INFO"

echo ""
echo "JVM参数:"
echo "$JVM_OPTS" | tr ' ' '\n' | grep -E '^-' | sort
echo ""
echo "应用参数:"
echo "$APP_OPTS" | tr ' ' '\n' | grep -E '^--'
echo ""

# 启动前检查
echo "启动前检查..."

# 检查端口是否被占用
if netstat -tuln | grep -q ":8080 "; then
    echo "警告: 端口8080已被占用"
    read -p "是否继续启动? (y/N): " -n 1 -r
    echo
    if [[ ! $REPLY =~ ^[Yy]$ ]]; then
        echo "启动取消"
        exit 1
    fi
fi

# 检查磁盘空间
DISK_USAGE=$(df -h . | awk 'NR==2 {print $5}' | sed 's/%//')
if [ "$DISK_USAGE" -gt 90 ]; then
    echo "警告: 磁盘使用率过高 ($DISK_USAGE%)"
fi

echo "开始启动应用..."
echo "命令: java $JVM_OPTS -jar $APP_JAR $APP_OPTS"
echo ""

# 启动应用
nohup java $JVM_OPTS -jar $APP_JAR $APP_OPTS > logs/application-$(date +%Y%m%d-%H%M%S).log 2>&1 &
APP_PID=$!

echo "应用已启动，PID: $APP_PID"
echo "日志文件: logs/application-$(date +%Y%m%d-%H%M%S).log"
echo "GC日志: logs/gc-$(date +%Y%m%d-%H%M%S).log"

# 保存PID到文件
echo $APP_PID > logs/app.pid

# 等待应用启动
echo ""
echo "等待应用启动..."
sleep 10

# 检查应用状态
if kill -0 $APP_PID 2>/dev/null; then
    echo "✅ 应用启动成功，PID: $APP_PID"
    
    # 尝试访问健康检查端点
    echo "检查应用健康状态..."
    for i in {1..30}; do
        if curl -s http://localhost:8080/actuator/health > /dev/null 2>&1; then
            echo "✅ 应用健康检查通过"
            break
        else
            echo "等待应用就绪... ($i/30)"
            sleep 2
        fi
    done
    
    echo ""
    echo "=== 启动完成 ==="
    echo "应用访问地址: http://localhost:8080"
    echo "管理端点: http://localhost:8080/actuator"
    echo "PID文件: logs/app.pid"
    echo ""
    echo "监控命令:"
    echo "  查看日志: tail -f logs/application-*.log"
    echo "  查看GC日志: tail -f logs/gc-*.log"
    echo "  查看进程: ps -p $APP_PID"
    echo "  停止应用: kill $APP_PID"
    echo ""
    echo "性能监控:"
    echo "  内存使用: jstat -gc $APP_PID"
    echo "  线程状态: jstack $APP_PID"
    echo "  堆转储: jmap -dump:format=b,file=heapdump.hprof $APP_PID"
    
else
    echo "❌ 应用启动失败"
    echo "请检查日志文件: logs/application-$(date +%Y%m%d-%H%M%S).log"
    exit 1
fi
